#include "app_device.h"
#include "thirdparty/log/log.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include "app_pool.h"

void app_device_defaultSendTask(void *arg)
{
    Device *device = arg;
    unsigned char buf[1024];
    // 从缓存中读取数据
    app_buffer_read(&device->send_buffer, buf, 3);
    app_buffer_read(&device->send_buffer, buf + 3, buf[1] + buf[2]);

    // 调用写前处理函数处理二进制数据
    int len = 0;
    if (device->vptr->pre_write)
    {
        len = device->vptr->pre_write(device, buf, 3 + buf[1] + buf[2]);
    }

    // 写入硬件
    if (len > 0)
    {
        write(device->fd, buf, len);
    }
}

void app_device_defaultRecvTask(void *arg)
{
    unsigned char buf[128];
    Device *device = arg;
    // 从缓存中读取消息数据
    app_buffer_read(&device->recv_buffer, buf, 3);
    app_buffer_read(&device->recv_buffer, buf + 3, buf[1] + buf[2]);

    // 调用接收回调函数, 将数据发送到mqtt服务器
    device->vptr->recv_callback(device, buf, 3 + buf[1] + buf[2]);
}

void *app_device_defaultBackgroundThread(void *arg)
{
    char buf[1024];
    Device *device = arg;
    Task task = {
        .task_func = device->vptr->recv_task,
        .argv = device};
    while (1)
    {
        // 从设备硬件中读取数据
        int read_len = read(device->fd, buf, 1024);
        if (read_len < 0)
        {
            continue;
        }

        // 经过兼容层代码二次处理
        if (device->vptr->post_read)
        {
            read_len = device->vptr->post_read(device, buf, read_len);
        }

        if (read_len > 0)
        {
            // 写入设备的recv_buffer
            app_buffer_write(&device->recv_buffer, buf, read_len);
            // 发送task，让线程池处理后续任务
            app_pool_registerTask(&task);
        }

    }
    return NULL;
}

int app_device_init(Device *device, char *filename)
{
    if (device->fd > 0)
    {
        log_warn("Device is already initialized");
        return -1;
    }

    device->vptr = malloc(sizeof(struct vTable));
    if (!device->vptr)
    {
        log_error("Failed to allocate memory for device vtable");
        goto DEVICE_VPTR_ALLOC_FAIL;
    }
    
    device->filename = malloc(strlen(filename) + 1);
    if (!device->filename)
    {
        log_error("Device filename alloc fail");
        goto DEVICE_FILENAME_ALLOC_FAIL;
    }

    if (app_buffer_init(&device->recv_buffer, 16 * 1024) < 0)
    {
        goto DEVICE_RECV_BUFFER_FAIL;
    }

    if (app_buffer_init(&device->send_buffer, 16 * 1024) < 0)
    {
        goto DEVICE_SEND_BUFFER_FAIL;
    }
    device->fd = open(filename, O_RDWR | O_NOCTTY);
    if (device->fd < 0)
    {
        log_error("Device open fail");
        goto DEVICE_OPEN_FAIL;
    }

    device->vptr->background_func = app_device_defaultBackgroundThread;
    device->vptr->post_read = NULL;
    device->vptr->pre_write = NULL;
    device->vptr->recv_task = app_device_defaultRecvTask;
    device->vptr->send_task = app_device_defaultSendTask;
    device->connection_type = CONNECTION_NONE;
    strcpy(device->filename, filename);

    device->is_running = 0;

    log_info("Device %s init success", filename);

    return 0;

DEVICE_OPEN_FAIL:
    app_buffer_free(&device->send_buffer);
DEVICE_SEND_BUFFER_FAIL:
    app_buffer_free(&device->recv_buffer);
DEVICE_RECV_BUFFER_FAIL:
    free(device->filename);
DEVICE_FILENAME_ALLOC_FAIL:
    free(device->vptr);
DEVICE_VPTR_ALLOC_FAIL:
    return -1;
}

int app_device_start(Device *device)
{
    if (device->is_running)
    {
        log_warn("Device is already running");
        return -1;
    }

    if (pthread_create(&device->background_thread, NULL, device->vptr->background_func, device) < 0)
    {
        log_error("Device create background thread fail");
        return -1;
    }

    device->is_running = 1;

    log_info("Device %s start", device->filename);
    return 0;
}

void app_device_registerRecvCallback(Device *device, int (*callback)(Device *, void *, int))
{
    // 设备可以通过调用该回调函数将数据发送到mqtt服务器
    device->vptr->recv_callback = callback;
}

int app_device_write(Device *device, void *ptr, int len)
{
    // 将数据写入设备发送缓存
    Task task = {
        .task_func = device->vptr->send_task,
        .argv = device};
    int result = app_buffer_write(&device->send_buffer, ptr, len);
    if (result < 0)
    {
        log_error("Device send buffer full");
        return -1;
    }

    // 注册一个发送任务，让线程池处理
    return app_pool_registerTask(&task);
}

int app_device_stop(Device *device)
{
    if (!device->is_running)
    {
        log_warn("Device is not running");
        return -1;
    }
    pthread_cancel(device->background_thread);
    pthread_join(device->background_thread, NULL);
    device->is_running = 0;

    log_info("Device %s stopped", device->filename);

    return 0;
}

void app_device_close(Device *device)
{
    if (device->is_running)
    {
        log_warn("Device is still running");
    }

    if (device->fd > 0)
    {
        close(device->fd);
        device->fd = -1;
        app_buffer_free(&device->send_buffer);
        app_buffer_free(&device->recv_buffer);
        free(device->filename);
        device->filename = NULL;
    }
}
